Skip to content

feat: improve external post embeds#2794

Merged
ghostdevv merged 6 commits into
npmx-dev:mainfrom
alexdln:feat/post-embeds-impr
Jun 17, 2026
Merged

feat: improve external post embeds#2794
ghostdevv merged 6 commits into
npmx-dev:mainfrom
alexdln:feat/post-embeds-impr

Conversation

@alexdln

@alexdln alexdln commented May 25, 2026

Copy link
Copy Markdown
Member

🧭 Context

Since I always think about improving the blog at the last minute, I'm doing it separately this time 🙃

Added full video support and improved post zones clickability. Now, in addition to video, we can also click to external embeds.

For video, I used an external library. It's the base approach for atproto projects, and I use it in mine as well

@vercel

vercel Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Jun 17, 2026 12:04am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Jun 17, 2026 12:04am
npmx-lunaria Ignored Ignored Jun 17, 2026 12:04am

Request Review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8f3ae08a-f43c-47d5-8d52-15876a741dbe

📥 Commits

Reviewing files that changed from the base of the PR and between 2125dec and 708708f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • app/components/VideoPlayer.vue
  • package.json
  • test/unit/a11y-component-coverage.spec.ts
✅ Files skipped from review due to trivial changes (1)
  • test/unit/a11y-component-coverage.spec.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • package.json
  • app/components/VideoPlayer.vue

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added a viewport-aware HLS video player with optional autoplay.
    • Enhanced Bluesky post embeds to support playlist embeds, make external content clickable, and use the new video player for video posts.
  • Chores
    • Updated security headers to include Bluesky video endpoints and allow blob: media sources.
    • Added hls.js dependency.
  • Tests
    • Excluded the new video player from accessibility component coverage checks.

Walkthrough

This PR adds HLS-based video playback: a new VideoPlayer component using hls.js with viewport-based autoplay, integrates it into BlueskyPostEmbed to render playlist-backed videos, and updates CSP media and connect sources, dependencies, and tests accordingly.

Changes

Video Streaming for Bluesky Embeds

Layer / File(s) Summary
VideoPlayer component with HLS and viewport-based playback
app/components/VideoPlayer.vue
New component declares src and autoplay props, manages Hls instance lifecycle with a watch and onScopeDispose, registers error handling, and uses useIntersectionObserver to conditionally play or pause based on visibility and autoplay.
BlueskyPostEmbed structural and video rendering updates
app/components/global/BlueskyPostEmbed.client.vue
Adds playlist?: string to the embed model, restructures the post container to a div with nested anchor, makes external embeds clickable, and replaces the thumbnail-based video UI with the VideoPlayer when post.embed?.playlist is present.
Security headers, dependency, and test update
modules/security-headers.ts, package.json, test/unit/a11y-component-coverage.spec.ts
CSP connect-src adds https://video.bsky.app and https://video.cdn.bsky.app; CSP media-src allows blob:; hls.js@1.6.16 added to dependencies; VideoPlayer.vue added to the accessibility test skip list.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly summarises the main objective of improving external post embeds by adding video support and enhanced clickability.
Description check ✅ Passed The description provides relevant context about the changes, explaining the addition of video support, improved clickability, and the use of an external library approach.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented May 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 21 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
app/components/VideoPlayer.vue 0.00% 18 Missing and 3 partials ⚠️

📢 Thoughts on this report? Let us know!

@github-actions

github-actions Bot commented May 25, 2026

Copy link
Copy Markdown

📊 Dependency Size Changes

Warning

This PR adds 24.8 MB of new dependencies, which exceeds the threshold of 200 kB.

📦 Package 📏 Size
hls.js@1.6.16 24.8 MB

Total size change: 24.8 MB

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/components/global/BlueskyPostEmbed.client.vue (1)

200-213: 💤 Low value

Consider whether viewport-based autoplay is desired.

The VideoPlayer component supports an autoplay prop that triggers play/pause based on viewport intersection, but it isn't passed here. If auto-play when scrolling into view is desired, add :autoplay="true". The current setup requires manual user interaction, which may be intentional given the controls and muted attributes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/components/global/BlueskyPostEmbed.client.vue` around lines 200 - 213,
The template rendering a VideoPlayer for playlist embeds omits the component's
viewport-based autoplay prop, so the video won't auto-play when scrolled into
view; decide whether autoplay-on-intersection is desired and if so add the
:autoplay="true" prop to the <VideoPlayer> usage (keeping existing props like
controls, muted, loop) to enable the component's intersection-driven play/pause
behavior, otherwise leave as-is to require manual interaction.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/components/VideoPlayer.vue`:
- Around line 22-24: The HLS error handler currently logs only the event name;
update the HLS listener registered with hls.on(Hls.Events.ERROR, ...) to accept
both parameters (event, data) and log the actual error details from data (e.g.,
data.type, data.details, data.response) instead of the event string, and handle
fatal errors by calling the Hls instance recovery/cleanup methods (e.g.,
hls.recoverMediaError(), hls.startLoad() or hls.destroy()) depending on
data.fatal; modify the callback signature and add branching for data.fatal to
attempt recovery or cleanup accordingly.

---

Nitpick comments:
In `@app/components/global/BlueskyPostEmbed.client.vue`:
- Around line 200-213: The template rendering a VideoPlayer for playlist embeds
omits the component's viewport-based autoplay prop, so the video won't auto-play
when scrolled into view; decide whether autoplay-on-intersection is desired and
if so add the :autoplay="true" prop to the <VideoPlayer> usage (keeping existing
props like controls, muted, loop) to enable the component's intersection-driven
play/pause behavior, otherwise leave as-is to require manual interaction.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: aa5c26f3-6d23-47e9-9bee-fbd45cb38d85

📥 Commits

Reviewing files that changed from the base of the PR and between db64da9 and 6bfe7d0.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • app/components/VideoPlayer.vue
  • app/components/global/BlueskyPostEmbed.client.vue
  • modules/security-headers.ts
  • package.json

Comment thread app/components/VideoPlayer.vue

@ghostdevv ghostdevv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume it's not possible to just use the video element with a link to the blob directly, rather than using hls.js? If not then I think we shouldn't load the library or the video until the user clicks on it

@alexdln

alexdln commented Jun 3, 2026

Copy link
Copy Markdown
Member Author

@ghostdevv this is the same approach as in bluesky - loads the logic immediately, and the video when it appears on the screen (with lazy attr)

Otherwise, you'd have to load the library first, and then the video would start loading. I'm not entirely sure that the optimization for those who didn't click justifies the experience for those who did...

@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedhls.js@​1.6.161001001009980

View full report

@ghostdevv ghostdevv added this pull request to the merge queue Jun 17, 2026
Merged via the queue into npmx-dev:main with commit 46e7c59 Jun 17, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants